﻿using System;
using System.Collections.Generic;
//using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
//using System.Threading.Tasks;

namespace NFCReader
{
    [
        Guid("72348274-67D0-47E5-B73F-07529FEDF30C"),
        ProgId("NFCPcscActiveX"),
        ClassInterface(ClassInterfaceType.None),
        ComDefaultInterface(typeof(IActiveX)),
        ComVisible(true)
    ]

    public class UC : IObjectSafety,IActiveX
    {
        private int retCode, hContext, hCard, hProtocol;
        private byte[] SendBuff = new byte[263];
        private byte[] RecvBuff = new byte[263];
        private int SendLen, RecvLen, Aprotocal;
        private ModWinsCard.SCARD_IO_REQUEST pioSendRequest, pioRecvPrequest;

        #region IObjectSafety 成员
        private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
        private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
        private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
        private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
        private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";
        private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
        private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
        private const int S_OK = 0;
        private const int E_FAIL = unchecked((int)0x80004005);
        private const int E_NOINTERFACE = unchecked((int)0x80004002);
        private bool _fSafeForScripting = true;
        private bool _fSafeForInitializing = true;

        public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
        {
            int Rslt = E_FAIL;
            string strGUID = riid.ToString("B");
            pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
            switch (strGUID)
            {
                case _IID_IDispatch:
                case _IID_IDispatchEx:
                    Rslt = S_OK;
                    pdwEnabledOptions = 0;
                    if (_fSafeForScripting == true)
                        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
                    break;
                case _IID_IPersistStorage:
                case _IID_IPersistStream:
                case _IID_IPersistPropertyBag:
                    Rslt = S_OK;
                    pdwEnabledOptions = 0;
                    if (_fSafeForInitializing == true)
                        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
                    break;
                default:
                    Rslt = E_NOINTERFACE;
                    break;
            }
            return Rslt;
        }
        public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
        {
            int Rslt = E_FAIL;
            string strGUID = riid.ToString("B");
            switch (strGUID)
            {
                case _IID_IDispatch:
                case _IID_IDispatchEx:
                    if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
                        Rslt = S_OK;
                    break;
                case _IID_IPersistStorage:
                case _IID_IPersistStream:
                case _IID_IPersistPropertyBag:
                    if(((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
                        Rslt = S_OK;
                    break;
                default:
                    Rslt = E_NOINTERFACE;
                    break;
            }
            return Rslt;
        }
        #endregion

        [SecuritySafeCritical]
        public int EstablishContext()
        {
            retCode = ModWinsCard.SCardEstablishContext(ModWinsCard.SCARD_SCOPE_USER, 0, 0, ref hContext);
            return retCode;
        }

        [SecuritySafeCritical]
        public int ConnectToReader(string readerName)
        {
            retCode = ModWinsCard.SCardConnect(this.hContext, readerName, ModWinsCard.SCARD_SHARE_SHARED, ModWinsCard.SCARD_PROTOCOL_T0 | ModWinsCard.SCARD_PROTOCOL_T1, ref hCard, ref hProtocol);
            return retCode;
        }

        [SecuritySafeCritical]
        public string Transmit(string command, int sendLen, int expectedRecvLen)
        {
            pioSendRequest.cbPciLength = 8;
            pioSendRequest.dwProtocol = this.hProtocol;

            pioRecvPrequest.cbPciLength = 8;
            pioRecvPrequest.dwProtocol = this.hProtocol;

            byte[] sendBuff = new byte[sendLen];

            int recvLen = expectedRecvLen;
            byte[] recvBuff = new byte[recvLen];

            sendBuff = StringToHex(command.Replace(" ", ""));

            retCode = ModWinsCard.SCardTransmit(this.hCard, ref pioSendRequest, ref sendBuff[0], sendLen, ref pioRecvPrequest, ref recvBuff[0], ref recvLen);

            string output = String.Empty;
            if (retCode != 0)
                output = retCode.ToString();
            else
                output = BitConverter.ToString(recvBuff).Replace("-", " ");

            return output;
        }

        [SecuritySafeCritical]
        public string GetSmartCardID()
        {
            string retMsg = this.Transmit("ffca000000", 5, 9);
            if (retMsg.Length >= 26)
            {
                retMsg = retMsg.Substring(0, 20);
            }
            return retMsg;
        }

        /// <summary>
        /// 创建资源管理器并获取系统连接的读卡器名称
        /// </summary>
        /// <returns>读写器名称或错误信息</returns>
        [SecuritySafeCritical]

        private string Init_ACR122()
        {
            retCode = ModWinsCard.SCardEstablishContext(ModWinsCard.SCARD_SCOPE_USER, 0, 0, ref hContext);
            if (ModWinsCard.SCARD_S_SUCCESS != retCode)
            {
                return "NFC Reader doesn't detected";
            }
            retCode= ModWinsCard.SCardConnect(this.hContext, "ACS ACR122 0", ModWinsCard.SCARD_SHARE_SHARED, ModWinsCard.SCARD_PROTOCOL_T0 | ModWinsCard.SCARD_PROTOCOL_T1, ref hCard, ref hProtocol);
            if (ModWinsCard.SCARD_S_SUCCESS != retCode)
                return "NFC Tag is removed";

            return retCode.ToString();
        }

        [SecuritySafeCritical]
        public string Read_Card()
        {

            return "";
        }

        [SecuritySafeCritical]
        public string Write_Card(string strCard)
        {
            return "";
        }

        [SecuritySafeCritical]
        public void ClearBuffers()
        {

        }

        [SecuritySafeCritical]
        private int SendAPDU()
        {

            return 0;
        }

        /// <summary>
        /// 十六进制字符串转字节数组
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [SecuritySafeCritical]
        private static byte[] StringToHex(string data)
        {
            int strLen = data.Length;
            int hexLen = 0;
            int idx = 0;
            byte[] output;

            if ((strLen % 2) == 0)
            {
                hexLen = strLen / 2;
            }
            else
            {
                hexLen = (strLen + 1) / 2;
                data = data.PadRight(strLen + 1, '0');
            }

            output = new byte[hexLen];

            for (idx = 0; idx < hexLen; idx++)
            {
                output[idx] = Convert.ToByte(data.Substring(idx * 2, 2), 16);
            }

            return output;
        }
    }
}